package cn.ticsmyc.tools.framework.main;


import cn.ticsmyc.tools.framework.ioc.context.ClassPathXmlApplicationContext;
import cn.ticsmyc.tools.framework.ioc.entity.BeanDefinition;
import cn.ticsmyc.tools.framework.ioc.factory.AutowiredCapableBeanFactory;
import cn.ticsmyc.tools.framework.ioc.io.ResourceLoader;
import cn.ticsmyc.tools.framework.ioc.reader.XmlBeanDefinitionReader;

import java.util.Map;
import java.util.concurrent.CyclicBarrier;

/**
 * @author Ticsmyc
 * @date 2021-05-24 17:32
 */
public class Test {


    public static void main(String[] args) throws Exception {
        testThreadSafe();
    }

    /**
     * 单例的线程安全问题测试
     * @throws Exception
     */
    public static void testThreadSafe() throws Exception {
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
        xmlBeanDefinitionReader.loadBeanDefinition("application-annotation.xml");

        AutowiredCapableBeanFactory beanFactory = new AutowiredCapableBeanFactory();

        Map<String, BeanDefinition> registry = xmlBeanDefinitionReader.getRegistry();
        registry.entrySet().forEach(entry -> {
            try {
                beanFactory.registerBeanDefinition(entry.getKey(), entry.getValue());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        CyclicBarrier cyclicBarrier = new CyclicBarrier(9);
        for (int i = 0; i < 10; ++i) {
            new Thread(()->{
                try{
                    cyclicBarrier.await();
                    Object hello = beanFactory.getBean("hello");
                    System.out.println(hello.hashCode());
                }catch(Exception e){
                    e.printStackTrace();
                }

            }).start();
        }

    }

    public static void testCircleRef() throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application-annotation.xml");
        WrapHello wrapHello = (WrapHello) classPathXmlApplicationContext.getBean("wrapHello");
        wrapHello.say();
    }

    public static void testAnnotationAutoWire() throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application-annotation.xml");
        Hello hello = (Hello) classPathXmlApplicationContext.getBean("hello");
        hello.say();

        WrapHello wrapHello = (WrapHello) classPathXmlApplicationContext.getBean("wrapHello");
        wrapHello.say();

    }

    /**
     * 测试单例和Prototype
     *
     * @throws Exception
     */
    public static void testPrototype() throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application.xml");
        WrapHello wrap = (WrapHello) classPathXmlApplicationContext.getBean("wrap");
        WrapHello wrap2 = (WrapHello) classPathXmlApplicationContext.getBean("wrap");
        System.out.println(wrap.equals(wrap2));
        System.out.println(wrap.hello.equals(wrap2.hello));
    }

    /**
     * 测试引用类型的注入
     *
     * @throws Exception
     */
    public static void testRefAutoWire() throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application.xml");
        WrapHello wrap = (WrapHello) classPathXmlApplicationContext.getBean("wrap");
        wrap.say();
    }

    /**
     * 测试ApplicationContext
     *
     * @throws Exception
     */
    public static void testApplicationContext() throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("application.xml");
        Hello hello = (Hello) classPathXmlApplicationContext.getBean("hello");
        hello.say();
    }

    /**
     * 测试BeanFactory
     *
     * @throws Exception
     */
    public static void testBeanFactory() throws Exception {
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
        xmlBeanDefinitionReader.loadBeanDefinition("application.xml");

        AutowiredCapableBeanFactory beanFactory = new AutowiredCapableBeanFactory();

        Map<String, BeanDefinition> registry = xmlBeanDefinitionReader.getRegistry();
        registry.entrySet().forEach(entry -> {
            try {
                beanFactory.registerBeanDefinition(entry.getKey(), entry.getValue());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        Hello hello = (Hello) beanFactory.getBean("hello");
        hello.say();

    }
}
